package com.sibbay.syncbox.utils;

import java.io.File;
import java.util.Stack;

import android.util.Log;

import com.sibbay.syncbox.Config;

/**
 * scan from root directory, skip hidden files/directories 
 * returns file name only
 * 
 *  root/dir1
 *  root/dir1/dir2/
 *  root/dir1/dir2/file1 <- return
 *  root/dir1/dir2/dir3/
 *  root/dir1/dir2/dir3/file2 <- return
 */
public final class FileIterator {
	private static final String TAG = FileIterator.class.getSimpleName();

	private final Stack<File[]>	mDir = new Stack<File[]>();
	private final Stack<Integer> mDirIdx = new Stack<Integer>();
	private final File[] mRootDir;

	public FileIterator(final File root) {
		mRootDir = root.listFiles();
	}
	
	// iterators
	
	public boolean moveToFirst() {
		if (mRootDir == null)
			return false;
		
		mDir.clear();
		mDirIdx.clear();
		mDir.push(mRootDir);
		mDirIdx.push(Integer.valueOf(0));
		return findFile(mDir, mDirIdx);
	}
	
	public boolean moveToNext() {
		final Integer i = mDirIdx.pop() + 1;
		mDirIdx.push(i);
		return findFile(mDir, mDirIdx);
	}
	
	// valid if iterator returns true
	
	String getName() {
		if (Config.DEBUG && (mDir.size() != mDirIdx.size())) 
			Log.e(TAG, "Direcory and Index DIFFERENT");
		
		return mDir.peek()[mDirIdx.peek()].getAbsolutePath();
	}
	
	public File getFile() {
		if (Config.DEBUG && (mDir.size() != mDirIdx.size())) 
			Log.e(TAG, "Direcory and Index DIFFERENT");

		return mDir.peek()[mDirIdx.peek()];
	}
	
	///
	
	private static boolean findFile(final Stack<File[]>	dir, final Stack<Integer> dirIdx) {
		while (true) {
			if (dir.size() == 0) {
				return false;
			}
			File[] ls = dir.peek();	
			int i = dirIdx.pop();
			while (i < ls.length) {
				final File f = ls[i];
//				Log.d(TAG, "name: " + i + " : " + f.getAbsolutePath());
				if (f.isHidden()) {
					i += 1;
					continue;
				}
				if (f.isFile()) {
					dirIdx.push(Integer.valueOf(i));
					return true;
				}
				final File[] d = f.listFiles();
				if (d == null || d.length == 0) {
					i += 1;
					continue;
				}
				dirIdx.push(Integer.valueOf(i+1));
				dir.push(d);
				
				ls = d;
				i = 0;
			}
			dir.pop();
		}		
	}
}
